package com.wonders.redisson;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @Description: TODO：测试相关功能
 * @Author: yyalin
 * @CreateDate: 2023/8/9 17:12
 * @Version: V1.0
 */
@Api(tags="测试Redisson相关功能点")
@RestController
@RequestMapping("/redisson")
@Slf4j
public class RedissonTest {
    @Autowired
    private RedissonClient redissonClient;
    //1、测试redisson最简单的分布式锁
    @ApiOperation(value="简单分布式锁操作", notes="easyRedisson")
    @GetMapping("/easyRedisson")
    public String easyRedisson() {
        //1.获取一把锁，只要锁的名字相同，就是同一把锁  其余锁也满足这个条件
        RLock lock = redissonClient.getLock("my-redission-lock");
        //2.加锁
        //redisson lock()存在看门狗机制（自动续期）详情见文档 默认30秒后解锁，
        // 但如果30秒结束后业务没结束，则会自动续期
        lock.lock();//阻塞等待式锁
        //lock(leaseTime,TimeUnit.SECONDS) 该方法不会自动续期
        //1、如果我们传递了锁的超时时间，就发送给redis执行lua脚本，进行占锁，默认超时就是我们指定的时间
        //2、如果我们未指定锁的超时时间，就使用30 * 1000 [LockWatchdogTimeout看i门狗的默认时间] ;
        //只要占锁成功，就会启动一个定时任务[重新给锁设置过期时间，新的过期时间就是看门狗的默认时间] , 每隔10s都会自动续期
        //internalLockLeaseTime [看门狗时间] / 3, 10s
        //最佳实践
        //1)、lock.lock(30,TimeUnit.SECONDS);省掉了整个续期操作。手动解锁
        try {
            log.info("加锁成功，执行业务" + Thread.currentThread().getId());
            Thread.sleep(3000);
        } catch (Exception e) {
            log.info("获取锁异常e："+e);
        } finally {
            //3.解锁 就算程序在解锁之前崩溃了，redisson也会自动解锁
            lock.unlock();
        }
        return "hello";
    }

    //1、测试分布式锁操作
    @ApiOperation(value="测试分布式锁操作", notes="testRedisson")
    @GetMapping("/testRedisson")
    public String testRedisson() throws InterruptedException {
        //1、获取锁(可重入)，并指定锁的名称
        rLock=redissonClient.getLock("lock:testRedisson");
        //2、尝试获取锁，参数分别是：waitTime:获取锁的最大等待时间(期间会重试)
        // leaseTime：锁自动释放时间  TimeUnit：时间单位
        //tryLock(long waitTime, long leaseTime, TimeUnit unit)
        boolean isLock=rLock.tryLock(1,100, TimeUnit.SECONDS);
        //3、判断锁获取成功及释放
        if(isLock){
            try {
                log.info("执行正常的业务......");
            }catch (Exception e){
                log.info("锁获取异常e："+e);
            }finally {
                //锁未关闭，则手动释放锁
                if(rLock.isLocked()){
                    rLock.unlock();
                    log.info("释放锁成功");
                }
            }
        }
        return "true";
    }

    private  RLock rLock=null;
    @ApiOperation(value="测试分布式锁的可重入锁原理", notes="testRedisson02")
    @GetMapping("/testRedisson02")
    public String testRedisson02() throws InterruptedException {
        //1、获取锁(可重入)，并指定锁的名称
        rLock=redissonClient.getLock("lock:testRedisson02");
        //2、尝试获取锁，参数分别是：waitTime:获取锁的最大等待时间(期间会重试)
        // leaseTime：锁自动释放时间  TimeUnit：时间单位
        //tryLock(long waitTime, long leaseTime, TimeUnit unit)
        boolean isLock=rLock.tryLock(1,100, TimeUnit.SECONDS);
        //3、判断锁获取成功及释放
        if(isLock){
            try {
                log.info("执行正常的业务02......");
                this.testRedisson03();
            }catch (Exception e){
                log.info("锁获取异常02e："+e);
            }finally {
                //锁未关闭，则手动释放锁
                if(rLock.isLocked()){
                    rLock.unlock();
                    log.info("释放锁成功02");
                }
            }
        }
        return "true";
    }
    public void testRedisson03() throws InterruptedException {
        //2、尝试获取锁，参数分别是：waitTime:获取锁的最大等待时间(期间会重试)
        // leaseTime：锁自动释放时间  TimeUnit：时间单位
        //tryLock(long waitTime, long leaseTime, TimeUnit unit)
        boolean isLock=rLock.tryLock(1,100, TimeUnit.SECONDS);
        //3、判断锁获取成功及释放
        if(isLock){
            try {
                log.info("执行正常的业务03......");
            }catch (Exception e){
                log.info("锁获取异常03e："+e);
            }finally {
                //锁未关闭，则手动释放锁
                if(rLock.isLocked()){
                    rLock.unlock();
                    log.info("释放锁成功03");
                }
            }
        }
    }


}
